 ///
 /// @file    Mystring.cc
 /// @author  lemon(haohb13@gmail.com)
 /// @date    2023-04-25 09:51:25
 ///
 
#include <string.h>

#include <vector>
#include <iostream>
using std::cout;
using std::endl;
using std::vector;

class String
{
public:
	String()
	: _pstr(new char[1]())
	{	cout << "String()" << endl;	}

    //explicit
	String(const char *pstr)
	: _pstr(new char[strlen(pstr) + 1]())
	{
		strcpy(_pstr, pstr);
		cout << "String(const char*)" << endl;
	}

    //注意：编译器不会自动提供具有移动语义的函数
    //具有移动语义的函数要优先于具有复制控制语义的函数的执行

    //移动构造函数
    String(String && rhs)
    : _pstr(rhs._pstr)
    {   //时间复杂为O(1)
        rhs._pstr = nullptr;
        cout << "String(String&&)" << endl;
    }

    //移动赋值运算符函数(移动赋值函数)
    String& operator=(String && rhs)
    {
        cout << "String & operator=(String &&)" << endl;
        delete [] _pstr;
        _pstr = rhs._pstr;
        rhs._pstr = nullptr;
        return *this;
    }

    //拷贝构造函数
	String(const String &rhs)
	: _pstr(new char[strlen(rhs._pstr) + 1]())
	{
		strcpy(_pstr, rhs._pstr);
		cout << "String(const String&)" << endl;
	}

    //赋值运算符函数(赋值函数)
	String &operator=(const String &rhs)
	{
        cout << "String& operator=(const String&)" << endl;
		if(this != &rhs) {
			delete [] _pstr;
			_pstr = new char[strlen(rhs._pstr) + 1]();
			strcpy(_pstr, rhs._pstr);
		}
		return *this;
	}

	~String()
	{
		delete [] _pstr;
		_pstr = nullptr;
		cout << "~String()" << endl;
	}

	void print() {
		if(_pstr) {
			cout << _pstr << endl;
		}
	}
    size_t length() const { return strlen(_pstr);   }
    const char * c_str() const {    return _pstr;   }

    friend std::ostream & operator<<(std::ostream & os, const String & rhs);
private:
	char * _pstr;
};

std::ostream & operator<<(std::ostream & os, const String & rhs)
{
    os << rhs._pstr;
    return os;
}
 
void test0() 
{
    vector<String> strs;
    strs.push_back("hello,world");

    //字符串在文字常量区
    cout <<  &"hello,world" << endl;
    cout <<  &"hello,world" << endl;
    const char * p = "hello,world";
    printf("p: %p\n", p);
} 

void test1()
{
    //&String("hello,world");//error 右值

    String s1("wuhan");
    &s1;//ok  左值
    String s2 = s1;//执行完该语句之后，s1不能发生改变

    //执行完该语句之后，右值可以发生改变,
    //而且还希望发生改变,把右值转移到s3中
    String s3 = String("wangdao");

    //const引用是一个万能引用
    //既可以绑定到左值，也可以绑定到右值
    const String & ref = s1;

    const String & ref2 = String("hello");
    //问题：当const引用作为函数参数时，无法识别出
    //传递过来的是左值还是右值, 因此无法进行转移操作
    //
    //转移操作的发生时机是传递过来的是一个右值时，才能进行；
    //如果传递过来的就是一个左值，是不可以执行转移操作的
    
    //提出的需求: 在语法层面希望能独立识别出右值
    //
    //C++11之前没有能够识别出右值的语法
    //C++11提出解决方案：右值引用
    
    //右值引用只能绑定到右值
    String && ref3 = String("hello");
    cout << "ref3:" << ref3 << endl;
    cout << "&ref3:" << &ref3 << endl;
    //String && ref4 = s1;//error 右值引用无法绑定到左值
    
    //右值引用诞生的目标是为了进行转移，所以意味着修改
    //const String &&   没有存在的意义 
}

void test3()
{
    String s1("hello");
    cout << "s1:" << s1 << endl;
    cout << "\n执行赋值操作:\n";
    s1 = String("world");
    cout << "s1:" << s1 << endl;
}
 
int main(void)
{
	/* test0(); */
    test3();
	return 0;
}
